﻿using System;
using System.Reflection;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;

// Author: Miroslav Matula m.matula@alutam.cz 
// Date : 11/8/2010

namespace Service.Web
{

  public class CustomService : DataService<CustomContext>
  {
    public static void InitializeService(DataServiceConfiguration config)
    {
      config.SetEntitySetAccessRule("*", EntitySetRights.All);
      config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
      config.MaxResultsPerCollection = 1000;
      config.DataServiceBehavior.AcceptCountRequests = true;
      config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
  }


  public class CustomContext : IUpdatable
  {

    private ProductList GetProductList()
    {
      return System.Web.HttpContext.Current.Session["products_odata"] as ProductList;
    }
    private void Delay()
    {
      string sdelay = (string)System.Web.HttpContext.Current.Session["servicedelay"];
      if(!string.IsNullOrEmpty(sdelay)) {
        int delay;
        int.TryParse(sdelay, out delay);
        if(delay > 0) System.Threading.Thread.Sleep(delay);
      }
    }

    // Query
    public IQueryable<Product> Products
    {
      get {
        Delay();
        return GetProductList().AsQueryable(); 
      }
    }

    #region IUpdatable Members

    public object CreateResource(string containerName, string fullTypeName)
    {
      // create object
      var objType = Type.GetType(fullTypeName);
      var resourceToAdd = Activator.CreateInstance(objType);
      // add the Product to the Products in-memory list
      GetProductList().Add((Product)resourceToAdd);

      return resourceToAdd;
    }

    public void DeleteResource(object targetResource)
    {
      // remove the Product form the Products list
      GetProductList().Remove((Product)targetResource);
    }

    public object GetResource(IQueryable query, string fullTypeName)
    {
      object result = null;

      var enumerator = query.GetEnumerator();

      while(enumerator.MoveNext()) {
        if(enumerator.Current != null) {
          result = enumerator.Current;
          break;
        }
      }

      if(fullTypeName != null && !fullTypeName.Equals(result.GetType().FullName)) {
        throw new DataServiceException();
      }

      return result;
    }

    public object GetValue(object targetResource, string propertyName)
    {
      // get the property info using reflection
      var targetType = targetResource.GetType();
      var targetProperty = targetType.GetProperty(propertyName);
      // retrun the value of the property
      return targetProperty.GetValue(targetResource, null);
    }

    public void SetValue(object targetResource, string propertyName, object propertyValue)
    {
      // get the property info using reflection
      Type targetType = targetResource.GetType();
      PropertyInfo property = targetType.GetProperty(propertyName);
      // set the property value
      property.SetValue(targetResource, propertyValue, null);
    }

    public object ResolveResource(object resource)
    {
      // nothing to do just return the resource
      return resource;
    }

    public void SaveChanges()
    {
      // object in memory - do nothing
    }

    public void SetReference(object targetResource, string propertyName, object propertyValue)
    {
      throw new NotImplementedException();
    }

    public object ResetResource(object resource)
    {
      throw new NotImplementedException();
    }

    public void ClearChanges()
    {
      throw new NotImplementedException();
    }

    public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
    {
      throw new NotImplementedException();
    }

    public void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
    {
      throw new NotImplementedException();
    }

    #endregion
  }

}
